<template>
  <div class="dynamic-table" v-loading="loading">
    <el-table
      ref="dynamicTable"
      :data="tableData"
      :row-key="getRowKeys"
      :header-cell-style="headerCellStyle"
      size="medium"
      v-bind="$attrs"
      v-on="$listeners"
    >
      <el-table-column
        v-if="type"
        :type="type"
        :reserve-selection="true"
        width="55"
      />
      <template v-for="(col, index) in columns">
        <el-table-column
          :key="col[rowKey] || index"
          v-bind="{...col}"
        >
          <template slot-scope="{ row }">
            <template v-if="col.slots">
              <template v-if="col.slots.customRender">
                <template v-if="col.actions">
                  <template v-for="(action, subIndex) in col.actions">
                    <el-popconfirm
                      v-if="action.type==='popconfirm'"
                      :key="subIndex"
                      title="您确定要删除吗？"
                      @confirm="actionEvent(row, action.func, 'del')"
                    >
                      <el-button
                        slot="reference"
                        v-bind="{...action.props}"
                        v-permission="action.permission"
                      >
                        {{ action.text }}
                      </el-button>
                    </el-popconfirm>
                    <el-button
                      v-else
                      v-permission="action.permission"
                      :key="subIndex"
                      v-bind="{...action.props}"
                      @click="actionEvent(row, action.func)"
                    >
                      {{ action.text }}
                    </el-button>
                  </template>
                </template>
                <slot v-else :name="col.slots.customRender" v-bind:row="row" />
              </template>
            </template>
            <template v-else>
              <template v-if="col.formatter">
                <span class="ellipsis-2">
                  {{ col.formatter(row) }}
                </span>
              </template>
              <template v-else>
                <span class="ellipsis-2">
                  {{ row[col.prop] }}
                </span>
              </template>
            </template>
          </template>
        </el-table-column>
      </template>
    </el-table>
    <div v-show="page.total" class="flex jc-flex-end mt-20">
      <el-pagination
        @size-change="onChangeSize"
        @current-change="onChangeNum"
        background
        :current-page.sync="page.pageCurrent"
        :page-sizes="[10, 20, 30, 40, 50]"
        :page-size.sync="page.pageSize"
        layout="total, prev, pager, next, sizes, jumper"
        :total="page.total"
      />
    </div>
  </div>
</template>

<script>
import permission from '@/directive/permission/index.js' // 权限判断指令
import { cloneDeep } from '@/utils/common.js'
// 参考ant-design-vue中的table
export default {
  name: 'dynamicTable',
  inheritAttrs: false,
  props: {
    // 行数据的Key，用来优化Table的渲染
    rowKey: {
      type: [String, Number],
      default: ''
    },
    columns: {
      type: Array,
      required: true
    },
    getListFunc: {
      // 获取列表数据函数API
      type: Function,
      required: true
    },
    type: {
      type: String,
      default: ''
    }
  },
  directives: { permission },
  computed: {
    headerCellStyle() {
      return {
        background: '#fafafa',
        color: 'rgba(0,0,0,.85)'
      }
    }
  },
  data() {
    return {
      // 表格数据
      tableData: [
        {
          id: 1,
          name: 'zgh1',
          content: '这是通过java修改的内容数据1',
          createdTime: '2021-06-06'
        },
        {
          id: 2,
          name: 'zgh2',
          content: '这是通过java修改的内容数据2',
          createdTime: '2021-06-06'
        }
      ],
      // 分页参数
      page: {
        pageCurrent: 1,
        pageSize: 10,
        total: 0
      },
      // 加载loading
      loading: false
    }
  },
  created () {
    this.refreshData()
  },
  methods: {
    getRowKeys(row) {
      return row[this.rowKey] || ''
    },
    /**
     * @param {object} params 表格查询参数
     * @param {boolean} flush 是否将页数重置到第一页
     * @description 获取表格数据
     */
    async refreshData(params = {}, flush = false) {
      const toString = Object.prototype.toString
      // 检测getListFunc为函数
      if (!toString.call(this.getListFunc).includes('Function')) return
      const queryParams = {
        pageCurrent: flush ? 1 : this.page.pageCurrent,
        pageSize: this.page.pageSize,
        ...params
      }
      this.loading = true
      const { list, page } = await this.getListFunc(queryParams).finally(() => { this.loading = false })
      this.tableData = list
      this.page.total = page.total
    },
    // 操作[按钮]事件
    async actionEvent(row, func, actionType = '') {
      // 深拷贝--防止误操作修改源数据
      const cloneRow = cloneDeep(row)
      // 将refreshData放入宏任务中，等待当前请求微任务拿到结果后进行判断操作
      await func({ row: cloneRow }, () => {
        const timer = setTimeout(() => {
          this.refreshData()
        }, 0)
        // 在destroyed钩子中请求定时器标识
        this.$off('hook:destroyed', () => {
          clearTimeout(timer)
        })
      })
      // 如果为删除操作，并且删除成功，当前的表格数据小于2条，则当前请求页面减一，即请求前一页数据
      if (actionType === 'del' && this.tableData.length < 2) {
        this.page.pageCurrent = Math.max(1, this.page.pageCurrent - 1)
      }
    },

    onChangeSize() {
      this.page.pageCurrent = 1
      this.refreshData()
    },
    onChangeNum() {
      this.refreshData()
    }
  }
}
</script>

<style lang="scss" scoped>
.dynamic-table {
  .el-button {
    margin: 0 10px 0 0;
  }
}
</style>
